package com.glidebitmappool;

import com.glidebitmappool.internal.Util;

import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.AllocatorType;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;

/**
 * 位图池使用类
 *
 * @author renpengfei
 * @since 2021-03-12
 */
public class GlideBitmapFactory {
    private static final String FORMAT = "image/png";
    private static HiLogLabel logLabel = new HiLogLabel(HiLog.LOG_APP, 0x001, "TAG");
    private static boolean isScale;

    private GlideBitmapFactory() {
    }

    /**
     * 根据路径获取解码图片
     *
     * @param pathName
     * @return PixelMap
     * @noinspection checkstyle:WhitespaceAround
     */
    public static PixelMap decodeFile(String pathName) {
        final ImageSource.DecodingOptions options = getDecodingOptions();

        isScale = true;

        PixelMap pixelMapFromPath = getPixelMapFromPath(pathName, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromPath.getImageInfo().size.width : 0,
                isScale ? pixelMapFromPath.getImageInfo().size.height : 0);

        options.sampleSize = 1;
        /**
         * 原库 API 大于11
         */
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = true;

        try {
            return getPixelMapFromPath(pathName, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromPath(pathName, options);
        }
    }

    /**
     * 根据路径获取解码图片
     *
     * @param pathName
     * @param reqWidth
     * @param reqHeight
     * @return PixelMap
     */
    public static PixelMap decodeFile(String pathName, int reqWidth, int reqHeight) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        isScale = true;
        PixelMap pixelMapFromPath = getPixelMapFromPath(pathName, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromPath.getImageInfo().size.width : 0,
                isScale ? pixelMapFromPath.getImageInfo().size.height : 0);

        options.sampleSize = Util.calculateInSampleSize(options, reqWidth, reqHeight);
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromPath(pathName, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromPath(pathName, options);
        }
    }

    /**
     * 根据资源id解码图片
     *
     * @param context
     * @param id
     * @return PixelMap
     */
    public static PixelMap decodeResource(Context context, int id) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        isScale = true;
        PixelMap pixelMapFromResource = getPixelMapFromResource(context, id, options);
//        HiLog.error(logLabel,"TAG-width---"+pixelMapFromResource.getImageInfo().size.width);
//        HiLog.error(logLabel,"TAG-height---"+pixelMapFromResource.getImageInfo().size.height);
        options.desiredSize = new Size(isScale
                ? pixelMapFromResource.getImageInfo().size.width : 0,
                isScale ? pixelMapFromResource.getImageInfo().size.height : 0);
        options.sampleSize = 1;
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = true;
        try {
            return getPixelMapFromResource(context, id, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromResource(context, id, options);
        }
    }

    /**
     * 根据资源id解码图片
     *
     * @param context
     * @param id
     * @param reqWidth
     * @param reqHeight
     * @return PixelMap
     */
    public static PixelMap decodeResource(Context context, int id, int reqWidth, int reqHeight) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        isScale = true;
        PixelMap pixelMapFromResource = getPixelMapFromResource(context, id, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromResource.getImageInfo().size.width : 0,
                isScale ? pixelMapFromResource.getImageInfo().size.height : 0);

        options.sampleSize = Util.calculateInSampleSize(options, reqWidth, reqHeight);
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromResource(context, id, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromResource(context, id, options);
        }
    }

    /**
     * 根据字节数组解码图片
     *
     * @param data
     * @param offset
     * @param length
     * @return PixelMap
     */
    public static PixelMap decodeByteArray(byte[] data, int offset, int length) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        isScale = true;
        PixelMap pixelMapFromArray = getPixelMapFromArray(data, offset, length, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromArray.getImageInfo().size.width : 0,
                isScale ? pixelMapFromArray.getImageInfo().size.height : 0);

        options.sampleSize = 1;
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromArray(data, offset, length, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromArray(data, offset, length, options);
        }
    }

    /**
     * 根据字节数据解码图片
     *
     * @param data
     * @param offset
     * @param length
     * @param reqWidth
     * @param reqHeight
     * @return PixelMap
     */
    public static PixelMap decodeByteArray(byte[] data, int offset, int length, int reqWidth, int reqHeight) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        isScale = true;
        PixelMap pixelMapFromArray = getPixelMapFromArray(data, offset, length, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromArray.getImageInfo().size.width : 0,
                isScale ? pixelMapFromArray.getImageInfo().size.height : 0);

        options.sampleSize = Util.calculateInSampleSize(options, reqWidth, reqHeight);
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromArray(data, offset, length, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromArray(data, offset, length, options);
        }
    }

    // decodeResourceStream 鸿蒙没有对应
    /* public static PixelMap decodeResourceStream(Resources res, TypedValue value, InputStream is, Rect pad) {
        final ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResourceStream(res, value, is, pad, options);
        options.sampleSize = 1;
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
            options.inBitmap = inBitmap;
        }
        options.inJustDecodeBounds = false;
        try {
            return BitmapFactory.decodeResourceStream(res, value, is, pad, options);
        } catch (IllegalArgumentException e) {
            options.inBitmap = null;
            return BitmapFactory.decodeResourceStream(res, value, is, pad, options);
        }
    }*/

    // decodeResourceStream 鸿蒙没有对应
    /* public static PixelMap decodeResourceStream(
            Resources res, TypedValue value, InputStream is, Rect pad, int reqWidth, int reqHeight) {
        final ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResourceStream(res, value, is, pad, options);
        options.sampleSize = Util.calculateInSampleSize(options, reqWidth, reqHeight);
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
            options.inBitmap = inBitmap;
        }
        options.inJustDecodeBounds = false;
        try {
            return BitmapFactory.decodeResourceStream(res, value, is, pad, options);
        } catch (IllegalArgumentException e) {
            options.inBitmap = null;
            return BitmapFactory.decodeResourceStream(res, value, is, pad, options);
        }
    }*/

    /**
     * 根据流数据解码图片
     *
     * @param is
     * @return PixelMap
     */
    public static PixelMap decodeStream(InputStream is) {
        final ImageSource.DecodingOptions options = getDecodingOptions();

        isScale = true;
        PixelMap pixelMapFromInputStream = getPixelMapFromInputStream(is, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromInputStream.getImageInfo().size.width : 0,
                isScale ? pixelMapFromInputStream.getImageInfo().size.height : 0);

        options.sampleSize = 1;
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromInputStream(is, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromInputStream(is, options);
        }
    }

    /**
     * 根据流数据解码图片
     *
     * @param is
     * @param reqWidth
     * @param reqHeight
     * @return PixelMap
     */
    public static PixelMap decodeStream(InputStream is, int reqWidth, int reqHeight) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        isScale = true;
        PixelMap pixelMapFromInputStream = getPixelMapFromInputStream(is, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromInputStream.getImageInfo().size.width : 0,
                isScale ? pixelMapFromInputStream.getImageInfo().size.height : 0);

        options.sampleSize = Util.calculateInSampleSize(options, reqWidth, reqHeight);
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromInputStream(is, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromInputStream(is, options);
        }
    }

    /**
     * 根据流数据解码图片
     *
     * @param is
     * @param outPadding
     * @return PixelMap
     */
    public static PixelMap decodeStream(InputStream is, Rect outPadding) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        isScale = true;
        options.desiredRegion = outPadding;
        PixelMap pixelMapFromInputStream = getPixelMapFromInputStream(is, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromInputStream.getImageInfo().size.width : 0,
                isScale ? pixelMapFromInputStream.getImageInfo().size.height : 0);

        options.sampleSize = 1;
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromInputStream(is, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromInputStream(is, options);
        }
    }

    /**
     * 根据流数据解码图片
     *
     * @param is
     * @param outPadding
     * @param reqWidth
     * @param reqHeight
     * @return PixelMap
     */
    public static PixelMap decodeStream(InputStream is, Rect outPadding, int reqWidth, int reqHeight) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        options.desiredRegion = outPadding;
        isScale = true;
        PixelMap pixelMapFromInputStream = getPixelMapFromInputStream(is, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromInputStream.getImageInfo().size.width : 0,
                isScale ? pixelMapFromInputStream.getImageInfo().size.height : 0);

        options.sampleSize = Util.calculateInSampleSize(options, reqWidth, reqHeight);
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromInputStream(is, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromInputStream(is, options);
        }
    }

    /**
     * 根据文件描述类解码图片
     *
     * @param fd
     * @return PixelMap
     */
    public static PixelMap decodeFileDescriptor(FileDescriptor fd) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        isScale = true;
        PixelMap pixelMapFromFileDescriptor = getPixelMapFromFileDescriptor(fd, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromFileDescriptor.getImageInfo().size.width : 0,
                isScale ? pixelMapFromFileDescriptor.getImageInfo().size.height : 0);

        options.sampleSize = 1;
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromFileDescriptor(fd, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromFileDescriptor(fd, options);
        }
    }

    /**
     * 根据文件描述类解码图片
     *
     * @param fd
     * @param reqWidth
     * @param reqHeight
     * @return PixelMap
     */
    public static PixelMap decodeFileDescriptor(FileDescriptor fd, int reqWidth, int reqHeight) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        isScale = true;
        PixelMap pixelMapFromFileDescriptor = getPixelMapFromFileDescriptor(fd, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromFileDescriptor.getImageInfo().size.width : 0,
                isScale ? pixelMapFromFileDescriptor.getImageInfo().size.height : 0);

        options.sampleSize = Util.calculateInSampleSize(options, reqWidth, reqHeight);
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromFileDescriptor(fd, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromFileDescriptor(fd, options);
        }
    }

    /**
     * 根据文件描述类解码图片
     *
     * @param fd
     * @param outPadding
     * @return PixelMap
     */
    public static PixelMap decodeFileDescriptor(FileDescriptor fd, Rect outPadding) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        options.desiredRegion = outPadding;
        isScale = true;
        PixelMap pixelMapFromFileDescriptor = getPixelMapFromFileDescriptor(fd, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromFileDescriptor.getImageInfo().size.width : 0,
                isScale ? pixelMapFromFileDescriptor.getImageInfo().size.height : 0);

        options.sampleSize = 1;
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromFileDescriptor(fd, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromFileDescriptor(fd, options);
        }
    }

    /**
     * 根据文件描述类解码图片
     *
     * @param fd
     * @param outPadding
     * @param reqWidth
     * @param reqHeight
     * @return PixelMap
     */
    public static PixelMap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, int reqWidth, int reqHeight) {
        final ImageSource.DecodingOptions options = getDecodingOptions();
        options.desiredRegion = outPadding;
        isScale = true;
        PixelMap pixelMapFromFileDescriptor = getPixelMapFromFileDescriptor(fd, options);
        options.desiredSize = new Size(isScale
                ? pixelMapFromFileDescriptor.getImageInfo().size.width : 0,
                isScale ? pixelMapFromFileDescriptor.getImageInfo().size.height : 0);

        options.sampleSize = Util.calculateInSampleSize(options, reqWidth, reqHeight);
        options.editable = true;
        PixelMap inBitmap = GlideBitmapPool.getBitmap(options.desiredSize.width,
                options.desiredSize.height, options.desiredPixelFormat);
        if (inBitmap != null && Util.canUseForInBitmap(inBitmap, options)) {
//            options.inBitmap = inBitmap;
        }
        isScale = false;
        try {
            return getPixelMapFromFileDescriptor(fd, options);
        } catch (IllegalArgumentException e) {
//            options.inBitmap = null;
            return getPixelMapFromFileDescriptor(fd, options);
        }
    }

    /**
     * 获取解码属性
     *
     * @return 解码属性
     */
    public static ImageSource.DecodingOptions getDecodingOptions() {
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        decodingOptions.allocator = AllocatorType.DEFAULT;
        decodingOptions.desiredRegion = new Rect(0, 0, 0, 0);
        decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;

        return decodingOptions;
    }

    /**
     * 根据存储路径获取位图
     *
     * @param path
     * @param decodingOptions
     * @return PixelMap
     */
    private static PixelMap getPixelMapFromPath(String path, ImageSource.DecodingOptions decodingOptions) {
        System.out.println("getPixelMapFromPath---" + path);
        PixelMap pixelmap = null;
        try {
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = FORMAT;
            ImageSource imageSource = ImageSource.create(path, sourceOptions);
            pixelmap = imageSource.createPixelmap(decodingOptions);
            return pixelmap;
        } catch (IllegalArgumentException e) {
            HiLog.error(logLabel, e.getMessage());
        }

        return pixelmap;
    }

    /**
     * 根据资源文件获取位图
     *
     * @param context
     * @param resId
     * @param decodingOptions
     * @return PixelMap
     */
    private static PixelMap getPixelMapFromResource(
            Context context, int resId, ImageSource.DecodingOptions decodingOptions) {
        InputStream drawableInputStream = null;
        PixelMap pixelmap = null;
        try {
            drawableInputStream = context.getResourceManager().getResource(resId);
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = FORMAT;
            ImageSource imageSource = ImageSource.create(drawableInputStream, sourceOptions);
            pixelmap = imageSource.createPixelmap(decodingOptions);
            return pixelmap;
        } catch (Exception e) {
            HiLog.error(logLabel, e.getMessage());
        } finally {
            try {
                if (drawableInputStream != null) {
                    drawableInputStream.close();
                }
            } catch (IOException e) {
                HiLog.error(logLabel, e.getMessage());
            }
        }
        return pixelmap;
    }

    /**
     * 从指定字节数组解码位图
     *
     * @param data
     * @param offset
     * @param length
     * @param decodingOptions
     * @return PixelMap
     */
    private static PixelMap getPixelMapFromArray(
            byte[] data, int offset, int length, ImageSource.DecodingOptions decodingOptions) {
        PixelMap pixelmap = null;
        try {
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = FORMAT;
            ImageSource imageSource = ImageSource.create(data, offset, length, sourceOptions);
            pixelmap = imageSource.createPixelmap(decodingOptions);
            return pixelmap;
        } catch (IllegalArgumentException e) {
            HiLog.error(logLabel, e.getMessage());
        }

        return pixelmap;
    }

    /**
     * 通过流数据解码位图
     *
     * @param inputStream
     * @param decodingOptions
     * @return PixelMap
     */
    private static PixelMap getPixelMapFromInputStream(
            InputStream inputStream, ImageSource.DecodingOptions decodingOptions) {
        PixelMap pixelmap = null;
        try {
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = FORMAT;
            ImageSource imageSource = ImageSource.create(inputStream, sourceOptions);
            pixelmap = imageSource.createPixelmap(decodingOptions);
            return pixelmap;
        } catch (IllegalArgumentException e) {
            HiLog.error(logLabel, e.getMessage());
        }
        return pixelmap;
    }

    /**
     * 通过文件描述解码位图
     *
     * @param fileDescriptor
     * @param decodingOptions
     * @return PixelMap
     */
    private static PixelMap getPixelMapFromFileDescriptor(
            FileDescriptor fileDescriptor, ImageSource.DecodingOptions decodingOptions) {
        PixelMap pixelmap = null;
        try {
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = FORMAT;
            ImageSource imageSource = ImageSource.create(fileDescriptor, sourceOptions);
            pixelmap = imageSource.createPixelmap(decodingOptions);
            return pixelmap;
        } catch (IllegalArgumentException e) {
            HiLog.error(logLabel, e.getMessage());
        }
        return pixelmap;
    }
}
